package com.sduept.nwld.dataserver.manager.protection;

import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.protection.ProtectionEquipment;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.cim.model.wires.Breaker;
import com.sduept.cim.model.wires.BusbarSection;
import com.sduept.cim.model.wires.PowerTransformer;
import com.sduept.core.dao.SuperDAO;
import com.sduept.generator.ObjectId;
import com.sduept.nwld.dataserver.controller.base.secondary.ProtectionEquipmentDTO;
import com.sduept.nwld.dataserver.manager.cim.BxCimManager;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.model.edata.cim.bx.BxSubstation;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

@Service
public class ProtectCheckQueryManager {
	@Autowired
	private SuperDAO dao;

	@Autowired
	private CimManager cm;
	@Autowired
	private BxCimManager bcm;
	@Autowired
	private MapDataCache cc;
	public static final String noPro="设备无保护";
	public static final String noMainPro="设备无主保护";
	public static final String onlyOneStationHasPro="只有一侧站有保护";
	public static final String proRepate="保护存在重复";
	public static final String proTypeIncomplete="保护种类不全";
	public static final String devTypeAsymmetric="保护型号不一致";
	public static final String proCountAsymmetric="两端主保护数量不一致";
	public static final String unbindSt="未关联变电站";
	public static final String unbindPrimary="未关联一次设备";
	
	/**
	 * 获得线路错误信息种类分组
	 * @return
	 */
	public List<String> getLineIncorrectKinds(){
		List<String> result = new ArrayList<String>();
		result.add(noMainPro);
		result.add(onlyOneStationHasPro);
		result.add(proRepate);
		result.add(proTypeIncomplete);
		result.add(devTypeAsymmetric);
		result.add(proCountAsymmetric);
		return result;
	}
	/**
	 * 获得母线错误信息种类分组
	 * @return
	 */
	public List<String> getBusIncorrectKinds(){
		List<String> result = new ArrayList<String>();
		result.add(noMainPro);
		result.add(proRepate);
		result.add(proTypeIncomplete);
		return result;
	}
	/**
	 * 获得变压器错误信息种类分组
	 * @return
	 */
	public List<String> getTransIncorrectKinds(){
		List<String> result = new ArrayList<String>();
		result.add(noMainPro);
		result.add(proRepate);
		result.add(proTypeIncomplete);
		return result;
	}
	/**
	 * 获得断路器错误信息种类分组
	 * @return
	 */
	public List<String> getBreakerIncorrectKinds(){
		List<String> result = new ArrayList<String>();
		result.add(noPro);
		result.add(proRepate);
		result.add(proTypeIncomplete);
		return result;
	}
	/**
	 * 获得未绑定变电站信息种类分组
	 * @return
	 */
	public List<String> getUnbindStKinds(){
		List<String> result = new ArrayList<String>();
//		result.add(noPro);
//		result.add(proTypeIncomplete);
		result.add(unbindSt);
		return result;
	}
	/**
	 * 获得未绑定一次设备信息种类分组
	 * @return
	 */
	public List<String> getUnbindPrimaryKinds(){
		List<String> result = new ArrayList<String>();
//		result.add(noPro);
//		result.add(proTypeIncomplete);
		result.add(unbindPrimary);
		return result;
	}
	/**
	 * 获得线路主保护错误信息
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getLineProtectIncorrectInfos(){
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		Map<String,List<ProtectionEquipment>> lineProtectCache = initLineMainProtectCache();
		generateErrorLineProtect(lineProtectCache, result);
		return result;
	}
	/**
	 * 获得母线主保护错误信息
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getBusProtectIncorrectInfos(){
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		Map<String,List<ProtectionEquipment>> lineProtectCache = initBusMainProtectCache();
		generateErrorBusProtect(lineProtectCache, result);
		return result;
	}
	/**
	 * 获得变压器主保护错误信息
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getTransProtectIncorrectInfos(){
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		Map<String,List<ProtectionEquipment>> lineProtectCache = initTransMainProtectCache();
		generateErrorTransProtect(lineProtectCache, result);
		return result;
	}
	/**
	 * 获得断路器保护错误信息
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getBreakerProtectIncorrectInfos(){
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		Map<String,List<ProtectionEquipment>> lineProtectCache = initBreakerProtectCache();
		generateErrorBreakerProtect(lineProtectCache, result);
		return result;
	}
	/**
	 * 获得没有绑定变电站的保护
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getUnbindStationProtect(){
		Map<String,BxSubstation> bxstationMap = getBxStations();
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		List<ProtectionEquipment> list= dao.findByCondition(ProtectionEquipment.class, "subId is null ");
		for(ProtectionEquipment pe:list){
			ProtectionEquipmentDTO dto = new ProtectionEquipmentDTO();
			try {
				BeanUtils.copyProperties(dto, pe);
				BxSubstation bxstation = bxstationMap.get(pe.getPrivateStationId());
				if(bxstation!=null){
					dto.setPrivateStationName(bxstation.getMname());
					dto.setComment("未绑定变电站");
				}
			} catch (IllegalAccessException | InvocationTargetException e) {
				e.printStackTrace();
			}
			result.add(dto);
		}
		return result;
	}
	/**
	 * 获得没有绑定一次设备的保护(500kV)
	 * @return
	 */
	public List<ProtectionEquipmentDTO> getUnbindPrimaryEquProtect(){
		Map<String,BxSubstation> bxstationMap = getBxStations();
		List<ProtectionEquipmentDTO> result = new ArrayList<ProtectionEquipmentDTO>();
		List<ProtectionEquipment> list= dao.findByCondition(ProtectionEquipment.class, "subId is not null AND protectedId is null AND standvoltage=500");
		for(ProtectionEquipment pe:list){
			ProtectionEquipmentDTO dto = new ProtectionEquipmentDTO();
			try {
				BeanUtils.copyProperties(dto, pe);
				BxSubstation bxstation = bxstationMap.get(pe.getPrivateStationId());
				dto.setPrivateStationName(bxstation.getMname());
				dto.setComment("未绑定一次设备");
			} catch (IllegalAccessException | InvocationTargetException e) {
				e.printStackTrace();
			}
			result.add(dto);
		}
		return result;
	}
	
	private Map<String,BxSubstation> getBxStations(){
		List<BxSubstation> bxstations = bcm.listAllBxSubstations();
		Map<String,BxSubstation> result = new HashMap<String, BxSubstation>();
		for(BxSubstation bs:bxstations){
			result.put(bs.getStationid(), bs);
		}
		return result;
	}
	/**
	 * 初始化线路主保护信息
	 */

	private Map<String,List<ProtectionEquipment>> initLineMainProtectCache(){
		Map<String,List<ProtectionEquipment>> lineProtectCache = new HashMap<String, List<ProtectionEquipment>>();
		String whereSql = " protectedType = '线路' and type like '主%' and protectedId is not null ";
		List<ProtectionEquipment>  list= dao.findByCondition(ProtectionEquipment.class,whereSql);
		for(ProtectionEquipment pe:list){
			List<ProtectionEquipment> pes = lineProtectCache.get(pe.getProtectedId());
			if(pes==null){
				pes = new ArrayList<ProtectionEquipment>();
				lineProtectCache.put(pe.getProtectedId(), pes);
			}
			pes.add(pe);
		}
		return lineProtectCache;
	}
	/**
	 * 初始化母线主保护信息
	 */

	private Map<String,List<ProtectionEquipment>> initBusMainProtectCache(){
		Map<String,List<ProtectionEquipment>> lineProtectCache = new HashMap<String, List<ProtectionEquipment>>();
		String whereSql = " protectedType = '母线' and type like '主%' and protectedId is not null ";
		List<ProtectionEquipment>  list= dao.findByCondition(ProtectionEquipment.class,whereSql);
		for(ProtectionEquipment pe:list){
			List<ProtectionEquipment> pes = lineProtectCache.get(pe.getProtectedId());
			if(pes==null){
				pes = new ArrayList<ProtectionEquipment>();
				lineProtectCache.put(pe.getProtectedId(), pes);
			}
			pes.add(pe);
		}
		return lineProtectCache;
	}
	/**
	 * 初始化变压器主保护信息
	 */

	private Map<String,List<ProtectionEquipment>> initTransMainProtectCache(){
		Map<String,List<ProtectionEquipment>> lineProtectCache = new HashMap<String, List<ProtectionEquipment>>();
		String whereSql = " protectedType = '变压器' and type like '主%' and protectedId is not null ";
		List<ProtectionEquipment>  list= dao.findByCondition(ProtectionEquipment.class,whereSql);
		for(ProtectionEquipment pe:list){
			List<ProtectionEquipment> pes = lineProtectCache.get(pe.getProtectedId());
			if(pes==null){
				pes = new ArrayList<ProtectionEquipment>();
				lineProtectCache.put(pe.getProtectedId(), pes);
			}
			pes.add(pe);
		}
		return lineProtectCache;
	}
	/**
	 * 初始化断路器保护信息
	 */

	private Map<String,List<ProtectionEquipment>> initBreakerProtectCache(){
		Map<String,List<ProtectionEquipment>> lineProtectCache = new HashMap<String, List<ProtectionEquipment>>();
		String whereSql = " protectedType = '断路器'  and protectedId is not null ";
		List<ProtectionEquipment>  list= dao.findByCondition(ProtectionEquipment.class,whereSql);
		for(ProtectionEquipment pe:list){
			List<ProtectionEquipment> pes = lineProtectCache.get(pe.getProtectedId());
			if(pes==null){
				pes = new ArrayList<ProtectionEquipment>();
				lineProtectCache.put(pe.getProtectedId(), pes);
			}
			pes.add(pe);
		}
		return lineProtectCache;
	}
	/**
	 * 初始化错误的线路保护 目前先取500kV
	 */
	private void generateErrorLineProtect(Map<String,List<ProtectionEquipment>> lineProtectCache,List<ProtectionEquipmentDTO> result){
		Collection<ACLineSegment> list = cc.getAcLineIdMapByVoltage(499,null).values();
		for(LineSegment ac:list){
			 List<ProtectionEquipment> plist = lineProtectCache.get(ac.getId());
			 if(plist==null){
				 String comment = noMainPro;
				 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
				 proDTO.setId(ObjectId.get().toString());
				 proDTO.setProtectedType("线路");
				 proDTO.setProtectedId(ac.getId());
				 proDTO.setProtectedName(ac.getName());
				 proDTO.setComment(comment);
				 result.add(proDTO);
			 }else{
				 //线路起始站主保护信息
				 List<ProtectionEquipment> startStPro = new ArrayList<ProtectionEquipment>();
				 //线路结束站主保护信息
				 List<ProtectionEquipment> endStPro = new ArrayList<ProtectionEquipment>();
				 for(ProtectionEquipment pe:plist){
					 if(ac.getStartST()!=null && ac.getStartST().equals(pe.getSubId())){
						 startStPro.add(pe);
					 }else if(ac.getEndST()!=null && ac.getEndST().equals(pe.getSubId())){
						 endStPro.add(pe);
					 }
				 }
				 try{
					 String comment = "";
					 if(startStPro.size()==0||endStPro.size()==0){
						 comment = onlyOneStationHasPro;
					 }else{
						 comment = checkLineProtectInfo(startStPro,endStPro);
					 }
					 if(StringUtils.isNotEmpty(comment)){
						 for(ProtectionEquipment pe:plist){
							 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
							 BeanUtils.copyProperties(proDTO, pe);
							 proDTO.setComment(comment);
							 result.add(proDTO);
						 }
					 }
				 }catch(Exception e){e.printStackTrace();}
			 }
		}
	}
	/**
	 * 初始化错误的母线保护 目前先取500kV
	 */
	private void generateErrorBusProtect(Map<String,List<ProtectionEquipment>> busProtectCache,List<ProtectionEquipmentDTO> result){
		List<BusbarSection> list = cm.getBusbarSectionsByStandVoltagelevel(499f);
		//key comment内容 value 数量
		for(BusbarSection ac:list){
			 List<ProtectionEquipment> plist = busProtectCache.get(ac.getId());
			 if(plist == null || plist.size()==0){
				 String comment = noMainPro;
				 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
				 proDTO.setId(ObjectId.get().toString());
				 proDTO.setSubstationId(ac.getSubId());
				 proDTO.setSubstationName(ac.getSubName());
				 proDTO.setProtectedType("母线");
				 proDTO.setProtectedName(ac.getName());
				 proDTO.setComment(comment);
				 result.add(proDTO);
			 }else{
				 try{
					 String comment =checkBusProtectInfo(plist);
					 if(StringUtils.isNotEmpty(comment)){
						 for(ProtectionEquipment pe:plist){
							 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
							 BeanUtils.copyProperties(proDTO, pe);
							 proDTO.setComment(comment);
							 result.add(proDTO);
						 }
					 }
				 }catch(Exception e){e.printStackTrace();}
			 }
		}
	}
	/**
	 * 初始化错误的变压器保护 
	 */
	private void generateErrorTransProtect(Map<String,List<ProtectionEquipment>> transProtectCache,List<ProtectionEquipmentDTO> result){
		List<PowerTransformer> list = cm.getAllPowerTransformers();
		for(PowerTransformer ac:list){
			 List<ProtectionEquipment> plist = transProtectCache.get(ac.getId());
			 if(plist == null || plist.size()==0){
				 String comment = noMainPro;
				 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
				 proDTO.setId(ObjectId.get().toString());
				 proDTO.setProtectedType("变压器");
				 proDTO.setSubstationId(ac.getSubId());
				 proDTO.setSubstationName(ac.getSubName());
				 proDTO.setProtectedName(ac.getName());
				 proDTO.setComment(comment);
				 result.add(proDTO);
			 }else{
				 try{
					 String comment =checkTransProtectInfo(plist);
					 if(StringUtils.isNotEmpty(comment)){
						 for(ProtectionEquipment pe:plist){
							 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
							 BeanUtils.copyProperties(proDTO, pe);
							 proDTO.setComment(comment);
							 result.add(proDTO);
						 }
					 }
				 }catch(Exception e){e.printStackTrace();}
			 }
		}
	}
	/**
	 * 初始化错误的断路器保护 
	 */
	private void generateErrorBreakerProtect(Map<String,List<ProtectionEquipment>> breakerProtectCache,List<ProtectionEquipmentDTO> result){
		List<Breaker> list = cm.getBreakerBySubNameAndvoltage500();
		for(Breaker ac:list){
			 List<ProtectionEquipment> plist = breakerProtectCache.get(ac.getId());
			 if(plist == null || plist.size()==0){
				 String comment = noPro;
				 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
				 proDTO.setId(ObjectId.get().toString());
				 proDTO.setProtectedType("断路器");
				 proDTO.setSubstationId(ac.getSubId());
				 proDTO.setSubstationName(ac.getSubName());
				 proDTO.setProtectedName(ac.getName());
				 proDTO.setComment(comment);
				 result.add(proDTO);
			 }else{
				 try{
					 String comment =checkBreakerProtectInfo(plist);
					 if(StringUtils.isNotEmpty(comment)){
						 for(ProtectionEquipment pe:plist){
							 ProtectionEquipmentDTO proDTO = new ProtectionEquipmentDTO();
							 BeanUtils.copyProperties(proDTO, pe);
							 proDTO.setComment(comment);
							 result.add(proDTO);
						 }
					 }
				 }catch(Exception e){e.printStackTrace();}
			 }
		}
	}
	/**
	 * 检测线路保护信息
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkLineProtectInfo(List<ProtectionEquipment> startStPro,List<ProtectionEquipment> endStPro){
		String result =checkCurrentStationMainProtectCount(startStPro);//检测开始站主一，二，三保护数量
		if(StringUtils.isEmpty(result)){
			result =checkCurrentStationMainProtectCount(endStPro);//检测结束站主一，二，三保护数量
			if(StringUtils.isEmpty(result)){
				result = checkLineProtectCoincident(startStPro, endStPro);//检测两侧站保护是否对称
				if(StringUtils.isEmpty(result)){
					result = checkLineProtectDevType(startStPro, endStPro);//检测两侧站保护型号是否一致
				}
			}
		}
		return result;
	}
	/**
	 * 检测母线保护信息
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkBusProtectInfo(List<ProtectionEquipment> stPro){
		String result =checkCurrentStationProtectType(stPro);//检测是否有主一，主二保护
		if(StringUtils.isEmpty(result)){
			result =checkCurrentStationMainProtectCount(stPro);//检测主一，二，三保护数量
			
		}
		return result;
	}
	/**
	 * 检测变压器保护信息
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkTransProtectInfo(List<ProtectionEquipment> stPro){
		String result =checkCurrentStationProtectType(stPro);//检测是否有主一，主二保护
		if(StringUtils.isEmpty(result)){
			result =checkCurrentStationMainProtectCount(stPro);//检测主一，二，三保护数量
			
		}
		return result;
	}
	/**
	 * 检测断路器保护信息
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkBreakerProtectInfo(List<ProtectionEquipment> stPro){
		String result = null;
		if(stPro.size()<3){
			result = proTypeIncomplete; 
		}
		if(StringUtils.isEmpty(result)){
			result =checkCurrentStationMainProtectCount(stPro);//检测主一，二，三保护数量
			
		}
		return result;
	}
	/**
	 * 检验变电站主保护数量
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkCurrentStationMainProtectCount(List<ProtectionEquipment> pros){
		int main1Count=0;
		int main2Count=0;
		int main3Count=0;
		for(ProtectionEquipment pe:pros){
			if("主一保护".equals(pe.getType())){
				main1Count++;
			}else if("主二保护".equals(pe.getType())){
				main2Count++;
			}else if("主三保护".equals(pe.getType())){
				main3Count++;
			}
		}
		if(main1Count>1||main2Count>1||main3Count>1){
			return proRepate;
		}
		return null;
	}
	/**
	 * 检验变电站各种类型的保护是否重复
	 * @param startStPro
	 * @param endStPro
	 * @return
	 */
	private String checkCurrentStationProtectCount(List<ProtectionEquipment> pros){
		Map<String,List<ProtectionEquipment>> map = new HashMap<>();
		for(ProtectionEquipment pe:pros){
			if(StringUtils.isNotEmpty(pe.getType())){
				List<ProtectionEquipment> list= map.get(pe.getType());
				if(list==null)
					list = new ArrayList<ProtectionEquipment>();
				list.add(pe);
			}
		}
		for(List<ProtectionEquipment> list :map.values()){
			if(list.size()>0)
				return proRepate;
		}
		return null;
	}
	/**
	 * 检测保护种类 用于母线，变压器  按设备必须有主一 主二 校验
	 * @param pros
	 * @return
	 */
	private String checkCurrentStationProtectType(List<ProtectionEquipment> pros){
		boolean main1 = false;
		boolean main2 = false;
		for(ProtectionEquipment pe:pros){
			if("主一保护".equals(pe.getType())){
				main1 = true;
			}else if("主二保护".equals(pe.getType())){
				main2 = true;
			}
		}
		if(!main1 || !main2){
			return proTypeIncomplete;
		}
		return null;
	}
	/**
	 * 检验线路保护两端站的主保护套数是否一致
	 * @return
	 */
	private String checkLineProtectCoincident(List<ProtectionEquipment> startStPros,List<ProtectionEquipment> endStPros){
		boolean shasMain1=false;
		boolean shasMain2=false;
		boolean shasMain3=false;
		
		boolean ehasMain1=false;
		boolean ehasMain2=false;
		boolean ehasMain3=false;
		for(ProtectionEquipment pe:startStPros){
			if("主一保护".equals(pe.getType())){
				shasMain1=true;
			}else if("主二保护".equals(pe.getType())){
				shasMain2=true;
			}else if("主三保护".equals(pe.getType())){
				shasMain3=true;
			}
		}
		for(ProtectionEquipment pe:endStPros){
			if("主一保护".equals(pe.getType())){
				ehasMain1=true;
			}else if("主二保护".equals(pe.getType())){
				ehasMain2=true;
			}else if("主三保护".equals(pe.getType())){
				ehasMain3=true;
			}
		}
		if(shasMain1!=ehasMain1 || shasMain2!=ehasMain2 ||shasMain3!=ehasMain3 ){
			return proCountAsymmetric;
		}
		return null;
	}
	/**
	 * 检验线路保护两端站的型号是否匹配
	 * @return
	 */
	private String checkLineProtectDevType(List<ProtectionEquipment> startStPros,List<ProtectionEquipment> endStPros){
		for(ProtectionEquipment spe:startStPros){
			for(ProtectionEquipment epe:endStPros){
				if(spe.getType().equals(epe.getType())){
					String sdevType = replaceChar(spe.getDevType());
					String edevType = replaceChar(epe.getDevType());
					if(StringUtils.isEmpty(sdevType) || StringUtils.isEmpty(edevType))
						return devTypeAsymmetric;
					else if(!sdevType.equalsIgnoreCase(edevType))
						return devTypeAsymmetric;
				}
			}
		}
		return null;
	}
	/**
	 * 截掉符号
	 * @param devType
	 * @return
	 */
	private String replaceChar(String devType){
		if(devType != null){
			devType = devType.replace("-", "").replace("_", "").replace("（", "").replace("(", "");
		}else{
			devType = "";
		}
		return devType;
	}
	
	/**
	 * 查询全部一次设备名称
	 * @return
	 */
	public List<?> queryAllProtectedName(){
		
		List<?> allProtectedName = dao.nativeQuery("select distinct protected_name from t_cim_protection_equipment where protected_name is not null");
		return allProtectedName;
	}
	
	/**
	 * 查询全部生产厂家
	 * @return
	 */
	public List<?> queryAllDev(){
		
		List<?> allDev = dao.nativeQuery("select dev_manufacturer from t_cim_protection_equipment where dev_manufacturer is not null and "
			+ "dev_manufacturer != '' group by dev_manufacturer");
		return allDev;
	}
	
	/**
	 * 查询全部一次设备类型
	 * @return
	 */
	public List<?> queryAllProtectedTypes(){
		
		List<?> allProtectedTypes = dao.nativeQuery("select protected_type from t_cim_protection_equipment where protected_type is not null and "
			+ "protected_type !=''  group by protected_type");
		return allProtectedTypes;
	}
	
	public void update(ProtectionEquipment pre){
		
		dao.update(pre, ProtectionEquipment.class);
	}
	
}
